/*
匿名内部类是重点，也是实现lambda表达式的原理。匿名内部类就是在new的时候，直接对接口或抽象类的实现。
我们不用单独创建一个类来实现，而是可以直接在new的时候写对应的实现。这样写无法复用。
为了方便， jdk默认为我们提供了专门写函数式的接口，比如consumer。
*/
package com.test.innerClass;

public class AnonymousInnerClasses {
    public static void main(String[] args) {
        Eat ie = new Eat() {  //输入这一行后，idea自动帮我们补全匿名内部类实现的代码，这样我们甚至可以实现接口。
            @Override
            public void eat() {
                //do something
            }
        };  //匿名内部类实现，后面要跟分号
        //接口中有一个方法，是可以这样写匿名内部类或lambda的，如果接口里面有多个方法，不能使用匿名内部方法或lambda表达式

        //lambda表达式，读作“来木大”表达式,其实就是接口匿名实现的简化，主要关注方法传入的参数和方法体
        //还是按照上面匿名内部类的写法，写完后，idea提示我们可以简化成lambda表达式，就简化成下面这个样子
        //()括号里面是传递的参数，{}里面是方法体，这里没有传递参数，也没有方法体，所以都是空
        Eat eat = () -> {};  //等价于上面的匿名函数内部类

        Sleep s = new Sleep() {
            @Override
            public String sleep(int i) {
                System.out.println("我睡" + i +"个小时才能有精神");
                return ("我睡" + i +"个小时才能有精神");  //接口的方法返回的String类型，提示方法体必须返回string
            }
        };

        //lambda表达式中使用的变量应为final或隐式final
        //lambda表达式（匿名内部类）只能访问外部的final类型或隐式final类型的局部变量。
        int c = 9;  //定义一个变量并赋值，这是隐式final
        c++;  //使用了c++ ，c值变化，就不是final了
        final int c1 = c; //或者我们定义一个final接收不是final的变量
        Sleep s1 = i -> c1+""; //使用final变量c1可以，可变变量c不可以，或者不让c进行c++也可以是隐式final

    }

}
